<!DOCTYPE html>












  


<html class="theme-next gemini use-motion" lang="zh-Hans">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
























<link rel="stylesheet" href="/lib/font-awesome/css/font-awesome.min.css?v=4.7.0">

<link rel="stylesheet" href="/css/main.css?v=7.1.2">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png?v=7.1.2">


  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png?v=7.1.2">


  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png?v=7.1.2">


  <link rel="mask-icon" href="/images/logo.svg?v=7.1.2" color="#222">







<script id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/',
    scheme: 'Gemini',
    version: '7.1.2',
    sidebar: {"position":"left","display":"post","offset":12,"onmobile":false,"dimmer":false},
    back2top: true,
    back2top_sidebar: false,
    fancybox: false,
    fastclick: false,
    lazyload: false,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>


  




  <meta name="description" content="人帅也要多读书，多学习，多运动">
<meta property="og:type" content="website">
<meta property="og:title" content="费曼的门徒">
<meta property="og:url" content="http://www.wuxiantao123.cn/page/2/index.html">
<meta property="og:site_name" content="费曼的门徒">
<meta property="og:description" content="人帅也要多读书，多学习，多运动">
<meta property="og:locale" content="zh-Hans">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="费曼的门徒">
<meta name="twitter:description" content="人帅也要多读书，多学习，多运动">





  
  
  <link rel="canonical" href="http://www.wuxiantao123.cn/page/2/">



<script id="page.configurations">
  CONFIG.page = {
    sidebar: "",
  };
</script>

  <title>费曼的门徒</title>
  












  <noscript>
  <style>
  .use-motion .motion-element,
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-title { opacity: initial; }

  .use-motion .logo,
  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-Hans">

  
  
    
  

  <div class="container sidebar-position-left 
  page-home">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta">
    

    <div class="custom-logo-site-title">
      <a href="/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">费曼的门徒</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
    
      
        <h1 class="site-subtitle" itemprop="description">Feynman follower</h1>
      
    
    
  </div>

  <div class="site-nav-toggle">
    <button aria-label="切换导航栏">
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>



<nav class="site-nav">
  
    <ul id="menu" class="menu">
      
        
        
        
          
          <li class="menu-item menu-item-home">

    
    
    
      
    

    

    <a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i> <br>首页</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-tags">

    
    
    
      
    

    

    <a href="/tags/" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i> <br>标签</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-categories">

    
    
    
      
    

    

    <a href="/categories/" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i> <br>分类</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-archives">

    
    
    
      
    

    

    <a href="/archives/" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i> <br>归档</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-备忘录">

    
    
    
      
    

    

    <a href="/books" rel="section"><i class="menu-item-icon fa fa-fw fa-book"></i> <br>备忘录</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-计划待办">

    
    
    
      
    

    

    <a href="/todolist" rel="section"><i class="menu-item-icon fa fa-fw fa-calendar"></i> <br>计划待办</a>

  </li>
        
        
        
          
          <li class="menu-item menu-item-about">

    
    
    
      
    

    

    <a href="/about/" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i> <br>关于</a>

  </li>

      
      
    </ul>
  

  

  
</nav>



  



</div>
    </header>

    
  
  

  

  <a href="https://github.com/peach-boy" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewbox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"/><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"/></svg></a>



    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          
            

          
          <div id="content" class="content">
            
  <section id="posts" class="posts-expand">
    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/19/记一次线上事故总结/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/19/记一次线上事故总结/" class="post-title-link" itemprop="url">记一次线上事故总结</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-19 22:40:45 / 修改时间：23:48:15" itemprop="dateCreated datePublished" datetime="2019-06-19T22:40:45+08:00">2019-06-19</time>
            

            
              

              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/代码之外/" itemprop="url" rel="index"><span itemprop="name">代码之外</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="事故起因"><a href="#事故起因" class="headerlink" title="事故起因"></a>事故起因</h3><p>发布预发布环境时，修改配置中心redis连接配置，连接密码错误，导致线上一个接口出现4000余个500请求</p>
<h3 id="事故经过"><a href="#事故经过" class="headerlink" title="事故经过"></a>事故经过</h3><p>当发布到预发布环境时，控制台立刻发现了错误日志，经排查发现是由于线上环境连接redis没有配置密码导致的。才想起本次上线引用了新开发的redis sdk，同时这个改造是由另外一个同事完成的。当时那位同事已经不再公司，于是就找架构师要了对应redis的连接密码，问题就发生在在这里了</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">配置一（线上使用的配置）</span><br><span class="line">host=redis.servers.test.jx</span><br><span class="line">port=6379</span><br><span class="line">password=</span><br><span class="line">database=9</span><br><span class="line">clientName=giveapp-rest</span><br><span class="line"></span><br><span class="line">配置二（新sdk使用的配置）</span><br><span class="line">spring.redis.host=redis.servers.test.jx</span><br><span class="line">spring.redis.port=6379</span><br><span class="line">spring.redis.password=</span><br><span class="line">spring.redis.database=14</span><br></pre></td></tr></table></figure>

<p>线上代码使用的是配置一，上线代码使用的是配置二，我将上述配置截图给架构师后，他将密码发给我，我拿到密码看到配置也在疑惑是使用哪一个配置（注释说明当时没有），<br>于是想当然的加到了两个配置上，自己在app上马上测试了一下，发现没有报错就没有在管了。大概过了几分钟同事告诉我说线上出问题了，我在自己的手机上上试了一下，果然redis相关接口报错，我迅速反应过来，马上把配置还原，问题解决。后来发现线上使用的配置一是可以需要密码的，架构师发给我的密码是配置二节点的密码，配置一和配置二的节点不一同一个，使用同一个密码，线上就会出现redis连接异常，这才是问题所在。另外一个问题，为什么自己修改完redis密码后，自己app没有异常，现在看来可能是客户端本地缓存，当然这个已经不重要，本身这种验证凡是也是及其愚蠢的。</p>
<h3 id="事故反思"><a href="#事故反思" class="headerlink" title="事故反思"></a>事故反思</h3><p>解决完后，自己也是自责不已，懊恼自己竟会做出如此草率的决定。回到家后，决定深入剖析一下当时自己的心路历程。回想起当时修改完后，自己验证”没问题后”，就被另一件事给耽搁住了，知道同事报障才反应过来。很多时候还是都是存在侥幸心理，以为会没问题。这让我想起了“墨菲定律”，任何小概率事假，看似几乎不能发生，当基数足够足够大时，它将会是必然时间。为什么会出现这次愚蠢的错误，究其原因还是因为自己之前也经常这么干，对有可能影响到线上的改动缺乏足够评估。综合来看，最近公司事故频发，大多数事故发生的场景都较为极端，甚至无法验证出来。但问题在于，这些代码问题或者不规范操作是长期存在的。当出现的次数不断增多时，事故的发生将会是一个必然事件。所以某种程度上，养成一个好的工作习惯是要胜过掌握一项新技术的。线上无小事，每一次关系到线上正常生产的改动，都需要再三保证其绝对正确，养成好的习惯。</p>

          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/markdown高阶语法/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/markdown高阶语法/" class="post-title-link" itemprop="url">markdown高阶语法</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 22:39:10 / 修改时间：22:49:45" itemprop="dateCreated datePublished" datetime="2019-06-18T22:39:10+08:00">2019-06-18</time>
            

            
              

              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/markdown/" itemprop="url" rel="index"><span itemprop="name">markdown</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h1 id="Markdown-高阶语法手册"><a href="#Markdown-高阶语法手册" class="headerlink" title="Markdown 高阶语法手册"></a>Markdown 高阶语法手册</h1><h3 id="1-内容目录"><a href="#1-内容目录" class="headerlink" title="1. 内容目录"></a>1. 内容目录</h3><p>在段落中填写 <code>[TOC]</code> 以显示全文内容的目录结构。</p>
<p>[TOC]</p>
<h3 id="2-标签分类"><a href="#2-标签分类" class="headerlink" title="2. 标签分类"></a>2. 标签分类</h3><p>在编辑区任意行的列首位置输入以下代码给文稿标签：</p>
<p>标签： 数学 英语 Markdown</p>
<p>或者</p>
<p>Tags： 数学 英语 Markdown</p>
<h3 id="3-删除线"><a href="#3-删除线" class="headerlink" title="3. 删除线"></a>3. 删除线</h3><p>使用 ~~ 表示删除线。</p>
<p><del>这是一段错误的文本。</del></p>
<h3 id="4-注脚"><a href="#4-注脚" class="headerlink" title="4. 注脚"></a>4. 注脚</h3><p>使用 [^keyword] 表示注脚。</p>
<p>这是一个注脚[^footnote]的样例。</p>
<p>这是第二个注脚[^footnote2]的样例。</p>
<h3 id="5-LaTeX-公式"><a href="#5-LaTeX-公式" class="headerlink" title="5. LaTeX 公式"></a>5. LaTeX 公式</h3><p>$ 表示行内公式： </p>
<p>质能守恒方程可以用一个很简洁的方程式 $E=mc^2$ 来表达。</p>
<p>$$ 表示整行公式：</p>
<p>$$\sum_{i=1}^n a_i=0$$</p>
<p>$$f(x_1,x_x,\ldots,x_n) = x_1^2 + x_2^2 + \cdots + x_n^2 $$</p>
<p>$$\sum^{j-1}<em>{k=0}{\widehat{\gamma}</em>{kj} z_k}$$</p>
<p>访问 <a href="http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference" target="_blank" rel="noopener">MathJax</a> 参考更多使用方法。</p>
<h3 id="6-加强的代码块"><a href="#6-加强的代码块" class="headerlink" title="6. 加强的代码块"></a>6. 加强的代码块</h3><p>支持四十一种编程语言的语法高亮的显示，行号显示。</p>
<p>非代码示例：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ sudo apt-get install vim-gnome</span><br></pre></td></tr></table></figure>

<p>Python 示例：</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@requires_authorization</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">somefunc</span><span class="params">(param1=<span class="string">''</span>, param2=<span class="number">0</span>)</span>:</span></span><br><span class="line">    <span class="string">'''A docstring'''</span></span><br><span class="line">    <span class="keyword">if</span> param1 &gt; param2: <span class="comment"># interesting</span></span><br><span class="line">        <span class="keyword">print</span> <span class="string">'Greater'</span></span><br><span class="line">    <span class="keyword">return</span> (param2 - param1 + <span class="number">1</span>) <span class="keyword">or</span> <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SomeClass</span>:</span></span><br><span class="line">    <span class="keyword">pass</span></span><br><span class="line"></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>message = <span class="string">'''interpreter</span></span><br><span class="line"><span class="string"><span class="meta">... </span>prompt'''</span></span><br></pre></td></tr></table></figure>

<p>JavaScript 示例：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* nth element in the fibonacci series.</span></span><br><span class="line"><span class="comment">* @param n &gt;= 0</span></span><br><span class="line"><span class="comment">* @return the nth element, &gt;= 0.</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fib</span>(<span class="params">n</span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> a = <span class="number">1</span>, b = <span class="number">1</span>;</span><br><span class="line">  <span class="keyword">var</span> tmp;</span><br><span class="line">  <span class="keyword">while</span> (--n &gt;= <span class="number">0</span>) &#123;</span><br><span class="line">    tmp = a;</span><br><span class="line">    a += b;</span><br><span class="line">    b = tmp;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> a;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="built_in">document</span>.write(fib(<span class="number">10</span>));</span><br></pre></td></tr></table></figure>

<h3 id="7-流程图"><a href="#7-流程图" class="headerlink" title="7. 流程图"></a>7. 流程图</h3><h4 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">st=&gt;start: Start:&gt;https://www.zybuluo.com</span><br><span class="line">io=&gt;inputoutput: verification</span><br><span class="line">op=&gt;operation: Your Operation</span><br><span class="line">cond=&gt;condition: Yes or No?</span><br><span class="line">sub=&gt;subroutine: Your Subroutine</span><br><span class="line">e=&gt;end</span><br><span class="line"></span><br><span class="line">st-&gt;io-&gt;op-&gt;cond</span><br><span class="line">cond(yes)-&gt;e</span><br><span class="line">cond(no)-&gt;sub-&gt;io</span><br></pre></td></tr></table></figure>

<h4 id="更多语法参考：流程图语法参考"><a href="#更多语法参考：流程图语法参考" class="headerlink" title="更多语法参考：流程图语法参考"></a>更多语法参考：<a href="http://adrai.github.io/flowchart.js/" target="_blank" rel="noopener">流程图语法参考</a></h4><h3 id="8-序列图"><a href="#8-序列图" class="headerlink" title="8. 序列图"></a>8. 序列图</h3><h4 id="示例-1"><a href="#示例-1" class="headerlink" title="示例 1"></a>示例 1</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">Alice-&gt;Bob: Hello Bob, how are you?</span><br><span class="line">Note right of Bob: Bob thinks</span><br><span class="line">Bob--&gt;Alice: I am good thanks!</span><br></pre></td></tr></table></figure>

<h4 id="示例-2"><a href="#示例-2" class="headerlink" title="示例 2"></a>示例 2</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Title: Here is a title</span><br><span class="line">A-&gt;B: Normal line</span><br><span class="line">B--&gt;C: Dashed line</span><br><span class="line">C-&gt;&gt;D: Open arrow</span><br><span class="line">D--&gt;&gt;A: Dashed open arrow</span><br></pre></td></tr></table></figure>

<h4 id="更多语法参考：序列图语法参考"><a href="#更多语法参考：序列图语法参考" class="headerlink" title="更多语法参考：序列图语法参考"></a>更多语法参考：<a href="http://bramp.github.io/js-sequence-diagrams/" target="_blank" rel="noopener">序列图语法参考</a></h4><h3 id="9-甘特图"><a href="#9-甘特图" class="headerlink" title="9. 甘特图"></a>9. 甘特图</h3><p>甘特图内在思想简单。基本是一条线条图，横轴表示时间，纵轴表示活动（项目），线条表示在整个期间上计划和实际的活动完成情况。它直观地表明任务计划在什么时候进行，及实际进展与计划要求的对比。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">title 项目开发流程</span><br><span class="line">section 项目确定</span><br><span class="line">    需求分析       :a1, 2016-06-22, 3d</span><br><span class="line">    可行性报告     :after a1, 5d</span><br><span class="line">    概念验证       : 5d</span><br><span class="line">section 项目实施</span><br><span class="line">    概要设计      :2016-07-05  , 5d</span><br><span class="line">    详细设计      :2016-07-08, 10d</span><br><span class="line">    编码          :2016-07-15, 10d</span><br><span class="line">    测试          :2016-07-22, 5d</span><br><span class="line">section 发布验收</span><br><span class="line">    发布: 2d</span><br><span class="line">    验收: 3d</span><br></pre></td></tr></table></figure>

<h4 id="更多语法参考：甘特图语法参考"><a href="#更多语法参考：甘特图语法参考" class="headerlink" title="更多语法参考：甘特图语法参考"></a>更多语法参考：<a href="https://knsv.github.io/mermaid/#gant-diagrams" target="_blank" rel="noopener">甘特图语法参考</a></h4><h3 id="10-Mermaid-流程图"><a href="#10-Mermaid-流程图" class="headerlink" title="10. Mermaid 流程图"></a>10. Mermaid 流程图</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">A[Hard edge] --&gt;|Link text| B(Round edge)</span><br><span class="line">B --&gt; C&#123;Decision&#125;</span><br><span class="line">C --&gt;|One| D[Result one]</span><br><span class="line">C --&gt;|Two| E[Result two]</span><br></pre></td></tr></table></figure>

<h4 id="更多语法参考：Mermaid-流程图语法参考"><a href="#更多语法参考：Mermaid-流程图语法参考" class="headerlink" title="更多语法参考：Mermaid 流程图语法参考"></a>更多语法参考：<a href="https://knsv.github.io/mermaid/#flowcharts-basic-syntax" target="_blank" rel="noopener">Mermaid 流程图语法参考</a></h4><h3 id="11-Mermaid-序列图"><a href="#11-Mermaid-序列图" class="headerlink" title="11. Mermaid 序列图"></a>11. Mermaid 序列图</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Alice-&gt;John: Hello John, how are you?</span><br><span class="line">loop every minute</span><br><span class="line">    John--&gt;Alice: Great!</span><br><span class="line">end</span><br></pre></td></tr></table></figure>

<h4 id="更多语法参考：Mermaid-序列图语法参考"><a href="#更多语法参考：Mermaid-序列图语法参考" class="headerlink" title="更多语法参考：Mermaid 序列图语法参考"></a>更多语法参考：<a href="https://knsv.github.io/mermaid/#sequence-diagrams" target="_blank" rel="noopener">Mermaid 序列图语法参考</a></h4><h3 id="12-表格支持"><a href="#12-表格支持" class="headerlink" title="12. 表格支持"></a>12. 表格支持</h3><table>
<thead>
<tr>
<th>项目</th>
<th align="right">价格</th>
<th align="center">数量</th>
</tr>
</thead>
<tbody><tr>
<td>计算机</td>
<td align="right">$1600</td>
<td align="center">5</td>
</tr>
<tr>
<td>手机</td>
<td align="right">$12</td>
<td align="center">12</td>
</tr>
<tr>
<td>管线</td>
<td align="right">$1</td>
<td align="center">234</td>
</tr>
</tbody></table>
<h3 id="13-定义型列表"><a href="#13-定义型列表" class="headerlink" title="13. 定义型列表"></a>13. 定义型列表</h3><dl><dt>名词 1</dt><dd>定义 1（左侧有一个可见的冒号和四个不可见的空格）</dd></dl><dl><dt>代码块 2</dt><dd>这是代码块的定义（左侧有一个可见的冒号和四个不可见的空格）</dd></dl><pre><code>代码块（左侧有八个不可见的空格）</code></pre><h3 id="14-Html-标签"><a href="#14-Html-标签" class="headerlink" title="14. Html 标签"></a>14. Html 标签</h3><p>本站支持在 Markdown 语法中嵌套 Html 标签，譬如，你可以用 Html 写一个纵跨两行的表格：</p>
<pre><code>&lt;table&gt;
    &lt;tr&gt;
        &lt;th rowspan=&quot;2&quot;&gt;值班人员&lt;/th&gt;
        &lt;th&gt;星期一&lt;/th&gt;
        &lt;th&gt;星期二&lt;/th&gt;
        &lt;th&gt;星期三&lt;/th&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
        &lt;td&gt;李强&lt;/td&gt;
        &lt;td&gt;张明&lt;/td&gt;
        &lt;td&gt;王平&lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;</code></pre><table>
    <tr>
        <th rowspan="2">值班人员</th>
        <th>星期一</th>
        <th>星期二</th>
        <th>星期三</th>
    </tr>
    <tr>
        <td>李强</td>
        <td>张明</td>
        <td>王平</td>
    </tr>
</table>

<h3 id="15-内嵌图标"><a href="#15-内嵌图标" class="headerlink" title="15. 内嵌图标"></a>15. 内嵌图标</h3><p>本站的图标系统对外开放，在文档中输入</p>
<pre><code>&lt;i class=&quot;icon-weibo&quot;&gt;&lt;/i&gt;</code></pre><p>即显示微博的图标： <i class="icon-weibo icon-2x"></i></p>
<p>替换 上述 <code>i 标签</code> 内的 <code>icon-weibo</code> 以显示不同的图标，例如：</p>
<pre><code>&lt;i class=&quot;icon-renren&quot;&gt;&lt;/i&gt;</code></pre><p>即显示人人的图标： <i class="icon-renren icon-2x"></i></p>
<p>更多的图标和玩法可以参看 <a href="http://fortawesome.github.io/Font-Awesome/3.2.1/icons/" target="_blank" rel="noopener">font-awesome</a> 官方网站。</p>
<h3 id="16-待办事宜-Todo-列表"><a href="#16-待办事宜-Todo-列表" class="headerlink" title="16. 待办事宜 Todo 列表"></a>16. 待办事宜 Todo 列表</h3><p>使用带有 [ ] 或 [x] （未完成或已完成）项的列表语法撰写一个待办事宜列表，并且支持子列表嵌套以及混用Markdown语法，例如：</p>
<pre><code>- [ ] **Cmd Markdown 开发**
    - [ ] 改进 Cmd 渲染算法，使用局部渲染技术提高渲染效率
    - [ ] 支持以 PDF 格式导出文稿
    - [x] 新增Todo列表功能 [语法参考](https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments)
    - [x] 改进 LaTex 功能
        - [x] 修复 LaTex 公式渲染问题
        - [x] 新增 LaTex 公式编号功能 [语法参考](http://docs.mathjax.org/en/latest/tex.html#tex-eq-numbers)
- [ ] **七月旅行准备**
    - [ ] 准备邮轮上需要携带的物品
    - [ ] 浏览日本免税店的物品
    - [x] 购买蓝宝石公主号七月一日的船票</code></pre><p>对应显示如下待办事宜 Todo 列表：</p>
<ul>
<li><input disabled type="checkbox"> <strong>Cmd Markdown 开发</strong><ul>
<li><input disabled type="checkbox"> 改进 Cmd 渲染算法，使用局部渲染技术提高渲染效率</li>
<li><input disabled type="checkbox"> 支持以 PDF 格式导出文稿</li>
<li><input checked disabled type="checkbox"> 新增Todo列表功能 <a href="https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments" target="_blank" rel="noopener">语法参考</a></li>
<li><input checked disabled type="checkbox"> 改进 LaTex 功能<ul>
<li><input checked disabled type="checkbox"> 修复 LaTex 公式渲染问题</li>
<li><input checked disabled type="checkbox"> 新增 LaTex 公式编号功能 <a href="http://docs.mathjax.org/en/latest/tex.html#tex-eq-numbers" target="_blank" rel="noopener">语法参考</a></li>
</ul>
</li>
</ul>
</li>
<li><input disabled type="checkbox"> <strong>七月旅行准备</strong><ul>
<li><input disabled type="checkbox"> 准备邮轮上需要携带的物品</li>
<li><input disabled type="checkbox"> 浏览日本免税店的物品</li>
<li><input checked disabled type="checkbox"> 购买蓝宝石公主号七月一日的船票</li>
</ul>
</li>
</ul>
<p>[^footnote]: 这是一个 <em>注脚</em> 的 <strong>文本</strong>。</p>
<p>[^footnote2]: 这是另一个 <em>注脚</em> 的 <strong>文本</strong>。</p>

          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/markdown简单语法/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/markdown简单语法/" class="post-title-link" itemprop="url">markdown简单语法</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 22:25:56 / 修改时间：22:49:34" itemprop="dateCreated datePublished" datetime="2019-06-18T22:25:56+08:00">2019-06-18</time>
            

            
              

              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/markdown/" itemprop="url" rel="index"><span itemprop="name">markdown</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="markdown语法"><a href="#markdown语法" class="headerlink" title="markdown语法"></a>markdown语法</h2><h3 id="1-斜体和粗体"><a href="#1-斜体和粗体" class="headerlink" title="1. 斜体和粗体"></a>1. 斜体和粗体</h3><p>使用 * 和 ** 表示斜体和粗体。</p>
<p>示例：</p>
<p>这是 <em>斜体</em>，这是 <strong>粗体</strong>。</p>
<h3 id="2-分级标题"><a href="#2-分级标题" class="headerlink" title="2. 分级标题"></a>2. 分级标题</h3><p>使用 === 表示一级标题，使用 — 表示二级标题。</p>
<p>示例：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">这是一个一级标题</span><br><span class="line">============================</span><br><span class="line"></span><br><span class="line">这是一个二级标题</span><br><span class="line">--------------------------------------------------</span><br><span class="line"></span><br><span class="line">### 这是一个三级标题</span><br></pre></td></tr></table></figure>

<p>你也可以选择在行首加井号表示不同级别的标题 (H1-H6)，例如：# H1, ## H2, ### H3，#### H4。</p>
<h3 id="3-外链接"><a href="#3-外链接" class="headerlink" title="3. 外链接"></a>3. 外链接</h3><p>使用 [描述](链接地址) 为文字增加外链接。</p>
<p>示例：<a href="http://www.wuxiantao123.cn">我的博客</a></p>
<h3 id="4-无序列表"><a href="#4-无序列表" class="headerlink" title="4. 无序列表"></a>4. 无序列表</h3><p>使用 *，+，- 表示无序列表。</p>
<p>示例：</p>
<ul>
<li>无序列表项 一</li>
<li>无序列表项 二</li>
<li>无序列表项 三</li>
</ul>
<h3 id="5-有序列表"><a href="#5-有序列表" class="headerlink" title="5. 有序列表"></a>5. 有序列表</h3><p>使用数字和点表示有序列表。</p>
<p>示例：</p>
<ol>
<li>有序列表项 一</li>
<li>有序列表项 二</li>
<li>有序列表项 三</li>
</ol>
<h3 id="6-文字引用"><a href="#6-文字引用" class="headerlink" title="6. 文字引用"></a>6. 文字引用</h3><p>使用 &gt; 表示文字引用。</p>
<p>示例：</p>
<blockquote>
<p>野火烧不尽，春风吹又生。</p>
</blockquote>
<h3 id="7-行内代码块"><a href="#7-行内代码块" class="headerlink" title="7. 行内代码块"></a>7. 行内代码块</h3><p>使用 `代码` 表示行内代码块。</p>
<p>示例：让我们聊聊 <code>html</code>。</p>
<h3 id="8-插入图像"><a href="#8-插入图像" class="headerlink" title="8.  插入图像"></a>8.  插入图像</h3><p>使用 ![描述](图片链接地址) 插入图像。</p>
<p>示例：</p>
<p><img src="https://www.zybuluo.com/static/img/my_head.jpg" alt="我的头像"></p>

          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/git常用命令/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/git常用命令/" class="post-title-link" itemprop="url">git常用命令</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 16:57:14" itemprop="dateCreated datePublished" datetime="2019-06-18T16:57:14+08:00">2019-06-18</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-07-02 19:21:32" itemprop="dateModified" datetime="2019-07-02T19:21:32+08:00">2019-07-02</time>
              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/git/" itemprop="url" rel="index"><span itemprop="name">git</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          <h2 id="git小记"><a href="#git小记" class="headerlink" title="git小记"></a>git小记</h2><h3 id="创建分支"><a href="#创建分支" class="headerlink" title="创建分支"></a>创建分支</h3><ol>
<li>git checkout -b develop_XXX origin/develop （以远程的develop分支为基准建立自己的本地分支）</li>
<li>git push origin develop_XXX（将本地develop_XXX分支提交到远程）</li>
</ol>
<h3 id="删除分支"><a href="#删除分支" class="headerlink" title="删除分支"></a>删除分支</h3><p> 1.git branch -D branchName（删除本地分支）</p>
<ol start="2">
<li>git push origin –delete branchName （删除远程分支）</li>
</ol>
          <!--noindex-->
          
            <div class="post-button text-center">
              <a class="btn" href="/2019/06/18/git常用命令/#more" rel="contents">
                阅读全文 &raquo;
              </a>
            </div>
          
          <!--/noindex-->
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/java多线程之常见面试问题/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/java多线程之常见面试问题/" class="post-title-link" itemprop="url">java多线程之常见面试问题</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 16:55:46" itemprop="dateCreated datePublished" datetime="2019-06-18T16:55:46+08:00">2019-06-18</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-07-09 16:24:17" itemprop="dateModified" datetime="2019-07-09T16:24:17+08:00">2019-07-09</time>
              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/java多线程/" itemprop="url" rel="index"><span itemprop="name">java多线程</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>多线程的常见问题</p>
<p>1、多线程有什么用？</p>
<p>一个可能在很多人看来很扯淡的一个问题：我会用多线程就好了，还管它有什么用？在我看来，这个回答更扯淡。所谓”知其然知其所以然”，”会用”只是”知其然”，”为什么用”才是”知其所以然”，只有达到”知其然知其所以然”的程度才可以说是把一个知识点运用自如。OK，下面说说我对这个问题的看法：</p>
<p>（1）发挥多核CPU的优势</p>
<p>随着工业的进步，现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的，4核、8核甚至16核的也都不少见，如果是单线程的程序，那么在双核CPU上就浪费了50%，在4核CPU上就浪费了75%。单核CPU上所谓的”多线程”那是假的多线程，同一时间处理器只会处理一段逻辑，只不过线程之间切换得比较快，看着像多个线程”同时”运行罢了。多核CPU上的多线程才是真正的多线程，它能让你的多段逻辑同时工作，多线程，可以真正发挥出多核CPU的优势来，达到充分利用CPU的目的。</p>
<p>（2）防止阻塞</p>
<p>从程序运行效率的角度来看，单核CPU不但不会发挥出多线程的优势，反而会因为在单核CPU上运行多线程导致线程上下文的切换，而降低程序整体的效率。但是单核CPU我们还是要应用多线程，就是为了防止阻塞。试想，如果单核CPU使用单线程，那么只要这个线程阻塞了，比方说远程读取某个数据吧，对端迟迟未返回又没有设置超时时间，那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题，多条线程同时运行，哪怕一条线程的代码执行读取数据阻塞，也不会影响其它任务的执行。</p>
<p>（3）便于建模</p>
<p>这是另外一个没有这么明显的优点了。假设有一个大的任务A，单线程编程，那么就要考虑很多，建立整个程序模型比较麻烦。但是如果把这个大的任务A分解成几个小任务，任务B、任务C、任务D，分别建立程序模型，并通过多线程分别运行这几个任务，那就简单很多了。</p>
<p>2、创建线程的方式</p>
<p>比较常见的一个问题了，一般就是两种：</p>
<p>（1）继承Thread类</p>
<p>（2）实现Runnable接口</p>
<p>至于哪个好，不用说肯定是后者好，因为实现接口的方式比继承类的方式更灵活，也能减少程序之间的耦合度，面向接口编程也是设计模式6大原则的核心。</p>
<p>3、start()方法和run()方法的区别</p>
<p>只有调用了start()方法，才会表现出多线程的特性，不同线程的run()方法里面的代码交替执行。如果只是调用run()方法，那么代码还是同步执行的，必须等待一个线程的run()方法里面的代码全部执行完毕之后，另外一个线程才可以执行其run()方法里面的代码。</p>
<p>4、Runnable接口和Callable接口的区别</p>
<p>有点深的问题了，也看出一个Java程序员学习知识的广度。</p>
<p>Runnable接口中的run()方法的返回值是void，它做的事情只是纯粹地去执行run()方法中的代码而已；Callable接口中的call()方法是有返回值的，是一个泛型，和Future、FutureTask配合可以用来获取异步执行的结果。</p>
<p>这其实是很有用的一个特性，因为多线程相比单线程更难、更复杂的一个重要原因就是因为多线程充满着未知性，某条线程是否执行了？某条线程执行了多久？某条线程执行的时候我们期望的数据是否已经赋值完毕？无法得知，我们能做的只是等待这条多线程的任务执行完毕而已。而Callable+Future/FutureTask却可以获取多线程运行的结果，可以在等待时间太长没获取到需要的数据的情况下取消该线程的任务，真的是非常有用。</p>
<p>5、CyclicBarrier和CountDownLatch的区别</p>
<p>两个看上去有点像的类，都在java.util.concurrent下，都可以用来表示代码运行到某个点上，二者的区别在于：</p>
<p>（1）CyclicBarrier的某个线程运行到某个点上之后，该线程即停止运行，直到所有的线程都到达了这个点，所有线程才重新运行；CountDownLatch则不是，某线程运行到某个点上之后，只是给某个数值-1而已，该线程继续运行</p>
<p>（2）CyclicBarrier只能唤起一个任务，CountDownLatch可以唤起多个任务</p>
<p>（3）CyclicBarrier可重用，CountDownLatch不可重用，计数值为0该CountDownLatch就不可再用了</p>
<p>6、volatile关键字的作用</p>
<p>一个非常重要的问题，是每个学习、应用多线程的Java程序员都必须掌握的。理解volatile关键字的作用的前提是要理解Java内存模型，这里就不讲Java内存模型了，可以参见第31点，volatile关键字的作用主要有两个：</p>
<p>（1）多线程主要围绕可见性和原子性两个特性而展开，使用volatile关键字修饰的变量，保证了其在多线程之间的可见性，即每次读取到volatile变量，一定是最新的数据</p>
<p>（2）代码底层执行不像我们看到的高级语言—-Java程序这么简单，它的执行是Java代码–&gt;字节码–&gt;根据字节码执行对应的C/C++代码–&gt;C/C++代码被编译成汇编语言–&gt;和硬件电路交互，现实中，为了获取更好的性能JVM可能会对指令进行重排序，多线程下可能会出现一些意想不到的问题。使用volatile则会对禁止语义重排序，当然这也一定程度上降低了代码执行效率</p>
<p>从实践角度而言，volatile的一个重要作用就是和CAS结合，保证了原子性，详细的可以参见java.util.concurrent.atomic包下的类，比如AtomicInteger。</p>
<p>7、什么是线程安全</p>
<p>又是一个理论的问题，各式各样的答案有很多，我给出一个个人认为解释地最好的：如果你的代码在多线程下执行和在单线程下执行永远都能获得一样的结果，那么你的代码就是线程安全的。</p>
<p>这个问题有值得一提的地方，就是线程安全也是有几个级别的：</p>
<p>（1）不可变</p>
<p>像String、Integer、Long这些，都是final类型的类，任何一个线程都改变不了它们的值，要改变除非新创建一个，因此这些不可变对象不需要任何同步手段就可以直接在多线程环境下使用</p>
<p>（2）绝对线程安全</p>
<p>不管运行时环境如何，调用者都不需要额外的同步措施。要做到这一点通常需要付出许多额外的代价，Java中标注自己是线程安全的类，实际上绝大多数都不是线程安全的，不过绝对线程安全的类，Java中也有，比方说CopyOnWriteArrayList、CopyOnWriteArraySet</p>
<p>（3）相对线程安全</p>
<p>相对线程安全也就是我们通常意义上所说的线程安全，像Vector这种，add、remove方法都是原子操作，不会被打断，但也仅限于此，如果有个线程在遍历某个Vector、有个线程同时在add这个Vector，99%的情况下都会出现ConcurrentModificationException，也就是fail-fast机制。</p>
<p>（4）线程非安全</p>
<p>这个就没什么好说的了，ArrayList、LinkedList、HashMap等都是线程非安全的类</p>
<p>8、Java中如何获取到线程dump文件</p>
<p>死循环、死锁、阻塞、页面打开慢等问题，打线程dump是最好的解决问题的途径。所谓线程dump也就是线程堆栈，获取到线程堆栈有两步：</p>
<p>（1）获取到线程的pid，可以通过使用jps命令，在Linux环境下还可以使用ps -ef | grep java</p>
<p>（2）打印线程堆栈，可以通过使用jstack pid命令，在Linux环境下还可以使用kill -3 pid</p>
<p>另外提一点，Thread类提供了一个getStackTrace()方法也可以用于获取线程堆栈。这是一个实例方法，因此此方法是和具体线程实例绑定的，每次获取获取到的是具体某个线程当前运行的堆栈，</p>
<p>9、一个线程如果出现了运行时异常会怎么样</p>
<p>如果这个异常没有被捕获的话，这个线程就停止执行了。另外重要的一点是：如果这个线程持有某个某个对象的监视器，那么这个对象监视器会被立即释放</p>
<p>10、如何在两个线程之间共享数据</p>
<p>通过在线程之间共享对象就可以了，然后通过wait/notify/notifyAll、await/signal/signalAll进行唤起和等待，比方说阻塞队列BlockingQueue就是为线程之间共享数据而设计的</p>
<p>11、sleep方法和wait方法有什么区别 </p>
<p>这个问题常问，sleep方法和wait方法都可以用来放弃CPU一定的时间，不同点在于如果线程持有某个对象的监视器，sleep方法不会放弃这个对象的监视器，wait方法会放弃这个对象的监视器</p>
<p>12、生产者消费者模型的作用是什么</p>
<p>这个问题很理论，但是很重要：</p>
<p>（1）通过平衡生产者的生产能力和消费者的消费能力来提升整个系统的运行效率，这是生产者消费者模型最重要的作用</p>
<p>（2）解耦，这是生产者消费者模型附带的作用，解耦意味着生产者和消费者之间的联系少，联系越少越可以独自发展而不需要收到相互的制约</p>
<p>13、ThreadLocal有什么用</p>
<p>简单说ThreadLocal就是一种以空间换时间的做法，在每个Thread里面维护了一个以开地址法实现的ThreadLocal.ThreadLocalMap，把数据进行隔离，数据不共享，自然就没有线程安全方面的问题了</p>
<p>14、为什么wait()方法和notify()/notifyAll()方法要在同步块中被调用</p>
<p>这是JDK强制的，wait()方法和notify()/notifyAll()方法在调用前都必须先获得对象的锁</p>
<p>15、wait()方法和notify()/notifyAll()方法在放弃对象监视器时有什么区别</p>
<p>wait()方法和notify()/notifyAll()方法在放弃对象监视器的时候的区别在于：wait()方法立即释放对象监视器，notify()/notifyAll()方法则会等待线程剩余代码执行完毕才会放弃对象监视器。</p>
<p>16、为什么要使用线程池</p>
<p>避免频繁地创建和销毁线程，达到线程对象的重用。另外，使用线程池还可以根据项目灵活地控制并发的数目。</p>
<p>17、怎么检测一个线程是否持有对象监视器</p>
<p>我也是在网上看到一道多线程面试题才知道有方法可以判断某个线程是否持有对象监视器：Thread类提供了一个holdsLock(Object obj)方法，当且仅当对象obj的监视器被某条线程持有的时候才会返回true，注意这是一个static方法，这意味着”某条线程”指的是当前线程。</p>
<p>18、synchronized和ReentrantLock的区别</p>
<p>synchronized是和if、else、for、while一样的关键字，ReentrantLock是类，这是二者的本质区别。既然ReentrantLock是类，那么它就提供了比synchronized更多更灵活的特性，可以被继承、可以有方法、可以有各种各样的类变量，ReentrantLock比synchronized的扩展性体现在几点上：</p>
<p>（1）ReentrantLock可以对获取锁的等待时间进行设置，这样就避免了死锁</p>
<p>（2）ReentrantLock可以获取各种锁的信息</p>
<p>（3）ReentrantLock可以灵活地实现多路通知</p>
<p>另外，二者的锁机制其实也是不一样的。ReentrantLock底层调用的是Unsafe的park方法加锁，synchronized操作的应该是对象头中mark word，这点我不能确定。</p>
<p>19、ConcurrentHashMap的并发度是什么</p>
<p>ConcurrentHashMap的并发度就是segment的大小，默认为16，这意味着最多同时可以有16条线程操作ConcurrentHashMap，这也是ConcurrentHashMap对Hashtable的最大优势，任何情况下，Hashtable能同时有两条线程获取Hashtable中的数据吗？</p>
<p>20、ReadWriteLock是什么</p>
<p>首先明确一下，不是说ReentrantLock不好，只是ReentrantLock某些时候有局限。如果使用ReentrantLock，可能本身是为了防止线程A在写数据、线程B在读数据造成的数据不一致，但这样，如果线程C在读数据、线程D也在读数据，读数据是不会改变数据的，没有必要加锁，但是还是加锁了，降低了程序的性能。</p>
<p>因为这个，才诞生了读写锁ReadWriteLock。ReadWriteLock是一个读写锁接口，ReentrantReadWriteLock是ReadWriteLock接口的一个具体实现，实现了读写的分离，读锁是共享的，写锁是独占的，读和读之间不会互斥，读和写、写和读、写和写之间才会互斥，提升了读写的性能。</p>
<p>21、FutureTask是什么</p>
<p>这个其实前面有提到过，FutureTask表示一个异步运算的任务。FutureTask里面可以传入一个Callable的具体实现类，可以对这个异步运算的任务的结果进行等待获取、判断是否已经完成、取消任务等操作。当然，由于FutureTask也是Runnable接口的实现类，所以FutureTask也可以放入线程池中。</p>
<p>22、Linux环境下如何查找哪个线程使用CPU最长</p>
<p>这是一个比较偏实践的问题，这种问题我觉得挺有意义的。可以这么做：</p>
<p>（1）获取项目的pid，jps或者ps -ef | grep java，这个前面有讲过</p>
<p>（2）top -H -p pid，顺序不能改变</p>
<p>这样就可以打印出当前的项目，每条线程占用CPU时间的百分比。注意这里打出的是LWP，也就是操作系统原生线程的线程号，我笔记本山没有部署Linux环境下的Java工程，因此没有办法截图演示，网友朋友们如果公司是使用Linux环境部署项目的话，可以尝试一下。</p>
<p>使用”top -H -p pid”+”jps pid”可以很容易地找到某条占用CPU高的线程的线程堆栈，从而定位占用CPU高的原因，一般是因为不当的代码操作导致了死循环。</p>
<p>最后提一点，”top -H -p pid”打出来的LWP是十进制的，”jps pid”打出来的本地线程号是十六进制的，转换一下，就能定位到占用CPU高的线程的当前线程堆栈了。</p>
<p>23、Java编程写一个会导致死锁的程序</p>
<p>第一次看到这个题目，觉得这是一个非常好的问题。很多人都知道死锁是怎么一回事儿：线程A和线程B相互等待对方持有的锁导致程序无限死循环下去。当然也仅限于此了，问一下怎么写一个死锁的程序就不知道了，这种情况说白了就是不懂什么是死锁，懂一个理论就完事儿了，实践中碰到死锁的问题基本上是看不出来的。</p>
<p>真正理解什么是死锁，这个问题其实不难，几个步骤：</p>
<p>（1）两个线程里面分别持有两个Object对象：lock1和lock2。这两个lock作为同步代码块的锁；</p>
<p>（2）线程1的run()方法中同步代码块先获取lock1的对象锁，Thread.sleep(xxx)，时间不需要太多，50毫秒差不多了，然后接着获取lock2的对象锁。这么做主要是为了防止线程1启动一下子就连续获得了lock1和lock2两个对象的对象锁</p>
<p>（3）线程2的run)(方法中同步代码块先获取lock2的对象锁，接着获取lock1的对象锁，当然这时lock1的对象锁已经被线程1锁持有，线程2肯定是要等待线程1释放lock1的对象锁的</p>
<p>这样，线程1”睡觉”睡完，线程2已经获取了lock2的对象锁了，线程1此时尝试获取lock2的对象锁，便被阻塞，此时一个死锁就形成了。代码就不写了，占的篇幅有点多，Java多线程7：死锁这篇文章里面有，就是上面步骤的代码实现。</p>
<p>24、怎么唤醒一个阻塞的线程</p>
<p>如果线程是因为调用了wait()、sleep()或者join()方法而导致的阻塞，可以中断线程，并且通过抛出InterruptedException来唤醒它；如果线程遇到了IO阻塞，无能为力，因为IO是操作系统实现的，Java代码并没有办法直接接触到操作系统。</p>
<p>25、不可变对象对多线程有什么帮助</p>
<p>前面有提到过的一个问题，不可变对象保证了对象的内存可见性，对不可变对象的读取不需要进行额外的同步手段，提升了代码执行效率。</p>
<p>26、什么是多线程的上下文切换</p>
<p>多线程的上下文切换是指CPU控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取CPU执行权的线程的过程。</p>
<p>27、如果你提交任务时，线程池队列已满，这时会发生什么</p>
<p>这里区分一下：</p>
<pre><code>如果使用的是无界队列LinkedBlockingQueue，也就是无界队列的话，没关系，继续添加任务到阻塞队列中等待执行，因为LinkedBlockingQueue可以近乎认为是一个无穷大的队列，可以无限存放任务
如果使用的是有界队列比如ArrayBlockingQueue，任务首先会被添加到ArrayBlockingQueue中，ArrayBlockingQueue满了，会根据maximumPoolSize的值增加线程数量，如果增加了线程数量还是处理不过来，ArrayBlockingQueue继续满，那么则会使用拒绝策略RejectedExecutionHandler处理满了的任务，默认是AbortPolicy</code></pre><p>28、Java中用到的线程调度算法是什么</p>
<p>抢占式。一个线程用完CPU之后，操作系统会根据线程优先级、线程饥饿情况等数据算出一个总的优先级并分配下一个时间片给某个线程执行。</p>
<p>29、Thread.sleep(0)的作用是什么</p>
<p>这个问题和上面那个问题是相关的，我就连在一起了。由于Java采用抢占式的线程调度算法，因此可能会出现某条线程常常获取到CPU控制权的情况，为了让某些优先级比较低的线程也能获取到CPU控制权，可以使用Thread.sleep(0)手动触发一次操作系统分配时间片的操作，这也是平衡CPU控制权的一种操作。</p>
<p>30、什么是自旋</p>
<p>很多synchronized里面的代码只是一些很简单的代码，执行时间非常快，此时等待的线程都加锁可能是一种不太值得的操作，因为线程阻塞涉及到用户态和内核态切换的问题。既然synchronized里面的代码执行得非常快，不妨让等待锁的线程不要被阻塞，而是在synchronized的边界做忙循环，这就是自旋。如果做了多次忙循环发现还没有获得锁，再阻塞，这样可能是一种更好的策略。</p>
<p>31、什么是Java内存模型</p>
<p>Java内存模型定义了一种多线程访问Java内存的规范。Java内存模型要完整讲不是这里几句话能说清楚的，我简单总结一下Java内存模型的几部分内容：</p>
<p>（1）Java内存模型将内存分为了主内存和工作内存。类的状态，也就是类之间共享的变量，是存储在主内存中的，每次Java线程用到这些主内存中的变量的时候，会读一次主内存中的变量，并让这些内存在自己的工作内存中有一份拷贝，运行自己线程代码的时候，用到这些变量，操作的都是自己工作内存中的那一份。在线程代码执行完毕之后，会将最新的值更新到主内存中去</p>
<p>（2）定义了几个原子操作，用于操作主内存和工作内存中的变量</p>
<p>（3）定义了volatile变量的使用规则</p>
<p>（4）happens-before，即先行发生原则，定义了操作A必然先行发生于操作B的一些规则，比如在同一个线程内控制流前面的代码一定先行发生于控制流后面的代码、一个释放锁unlock的动作一定先行发生于后面对于同一个锁进行锁定lock的动作等等，只要符合这些规则，则不需要额外做同步措施，如果某段代码不符合所有的happens-before规则，则这段代码一定是线程非安全的</p>
<p>32、什么是CAS</p>
<p>CAS，全称为Compare and Swap，即比较-替换。假设有三个操作数：内存值V、旧的预期值A、要修改的值B，当且仅当预期值A和内存值V相同时，才会将内存值修改为B并返回true，否则什么都不做并返回false。当然CAS一定要volatile变量配合，这样才能保证每次拿到的变量是主内存中最新的那个值，否则旧的预期值A对某条线程来说，永远是一个不会变的值A，只要某次CAS操作失败，永远都不可能成功。</p>
<p>33、什么是乐观锁和悲观锁</p>
<p>（1）乐观锁：就像它的名字一样，对于并发间操作产生的线程安全问题持乐观状态，乐观锁认为竞争不总是会发生，因此它不需要持有锁，将比较-替换这两个动作作为一个原子操作尝试去修改内存中的变量，如果失败则表示发生冲突，那么就应该有相应的重试逻辑。</p>
<p>（2）悲观锁：还是像它的名字一样，对于并发间操作产生的线程安全问题持悲观状态，悲观锁认为竞争总是会发生，因此每次对某资源进行操作时，都会持有一个独占的锁，就像synchronized，不管三七二十一，直接上了锁就操作资源了。</p>
<p>34、什么是AQS</p>
<p>简单说一下AQS，AQS全称为AbstractQueuedSychronizer，翻译过来应该是抽象队列同步器。</p>
<p>如果说java.util.concurrent的基础是CAS的话，那么AQS就是整个Java并发包的核心了，ReentrantLock、CountDownLatch、Semaphore等等都用到了它。AQS实际上以双向队列的形式连接所有的Entry，比方说ReentrantLock，所有等待的线程都被放在一个Entry中并连成双向队列，前面一个线程使用ReentrantLock好了，则双向队列实际上的第一个Entry开始运行。</p>
<p>AQS定义了对双向队列所有的操作，而只开放了tryLock和tryRelease方法给开发者使用，开发者可以根据自己的实现重写tryLock和tryRelease方法，以实现自己的并发功能。</p>
<p>35、单例模式的线程安全性</p>
<p>老生常谈的问题了，首先要说的是单例模式的线程安全意味着：某个类的实例在多线程环境下只会被创建一次出来。单例模式有很多种的写法，我总结一下：</p>
<p>（1）饿汉式单例模式的写法：线程安全</p>
<p>（2）懒汉式单例模式的写法：非线程安全</p>
<p>（3）双检锁单例模式的写法：线程安全</p>
<p>36、Semaphore有什么作用</p>
<p>Semaphore就是一个信号量，它的作用是限制某段代码块的并发数。Semaphore有一个构造函数，可以传入一个int型整数n，表示某段代码最多只有n个线程可以访问，如果超出了n，那么请等待，等到某个线程执行完毕这段代码块，下一个线程再进入。由此可以看出如果Semaphore构造函数中传入的int型整数n=1，相当于变成了一个synchronized了。</p>
<p>37、Hashtable的size()方法中明明只有一条语句”return count”，为什么还要做同步？</p>
<p>这是我之前的一个困惑，不知道大家有没有想过这个问题。某个方法中如果有多条语句，并且都在操作同一个类变量，那么在多线程环境下不加锁，势必会引发线程安全问题，这很好理解，但是size()方法明明只有一条语句，为什么还要加锁？</p>
<p>关于这个问题，在慢慢地工作、学习中，有了理解，主要原因有两点：</p>
<p>（1）同一时间只能有一条线程执行固定类的同步方法，但是对于类的非同步方法，可以多条线程同时访问。所以，这样就有问题了，可能线程A在执行Hashtable的put方法添加数据，线程B则可以正常调用size()方法读取Hashtable中当前元素的个数，那读取到的值可能不是最新的，可能线程A添加了完了数据，但是没有对size++，线程B就已经读取size了，那么对于线程B来说读取到的size一定是不准确的。而给size()方法加了同步之后，意味着线程B调用size()方法只有在线程A调用put方法完毕之后才可以调用，这样就保证了线程安全性</p>
<p>（2）CPU执行代码，执行的不是Java代码，这点很关键，一定得记住。Java代码最终是被翻译成机器码执行的，机器码才是真正可以和硬件电路交互的代码。即使你看到Java代码只有一行，甚至你看到Java代码编译之后生成的字节码也只有一行，也不意味着对于底层来说这句语句的操作只有一个。一句”return count”假设被翻译成了三句汇编语句执行，一句汇编语句和其机器码做对应，完全可能执行完第一句，线程就切换了。</p>
<p>38、线程类的构造方法、静态块是被哪个线程调用的</p>
<p>这是一个非常刁钻和狡猾的问题。请记住：线程类的构造方法、静态块是被new这个线程类所在的线程所调用的，而run方法里面的代码才是被线程自身所调用的。</p>
<p>如果说上面的说法让你感到困惑，那么我举个例子，假设Thread2中new了Thread1，main函数中new了Thread2，那么：</p>
<p>（1）Thread2的构造方法、静态块是main线程调用的，Thread2的run()方法是Thread2自己调用的</p>
<p>（2）Thread1的构造方法、静态块是Thread2调用的，Thread1的run()方法是Thread1自己调用的</p>
<p>39、同步方法和同步块，哪个是更好的选择</p>
<p>同步块，这意味着同步块之外的代码是异步执行的，这比同步整个方法更提升代码的效率。请知道一条原则：同步的范围越小越好。</p>
<p>借着这一条，我额外提一点，虽说同步的范围越少越好，但是在Java虚拟机中还是存在着一种叫做锁粗化的优化方法，这种方法就是把同步范围变大。这是有用的，比方说StringBuffer，它是一个线程安全的类，自然最常用的append()方法是一个同步方法，我们写代码的时候会反复append字符串，这意味着要进行反复的加锁-&gt;解锁，这对性能不利，因为这意味着Java虚拟机在这条线程上要反复地在内核态和用户态之间进行切换，因此Java虚拟机会将多次append方法调用的代码进行一个锁粗化的操作，将多次的append的操作扩展到append方法的头尾，变成一个大的同步块，这样就减少了加锁–&gt;解锁的次数，有效地提升了代码执行的效率。</p>
<p>40、高并发、任务执行时间短的业务怎样使用线程池？并发不高、任务执行时间长的业务怎样使用线程池？并发高、业务执行时间长的业务怎样使用线程池？</p>
<p>这是我在并发编程网上看到的一个问题，把这个问题放在最后一个，希望每个人都能看到并且思考一下，因为这个问题非常好、非常实际、非常专业。关于这个问题，个人看法是：</p>
<p>（1）高并发、任务执行时间短的业务，线程池线程数可以设置为CPU核数+1，减少线程上下文的切换</p>
<p>（2）并发不高、任务执行时间长的业务要区分开看：</p>
<p>　　a）假如是业务时间长集中在IO操作上，也就是IO密集型的任务，因为IO操作并不占用CPU，所以不要让所有的CPU闲下来，可以加大线程池中的线程数目，让CPU处理更多的业务</p>
<p>　　b）假如是业务时间长集中在计算操作上，也就是计算密集型任务，这个就没办法了，和（1）一样吧，线程池中的线程数设置得少一些，减少线程上下文的切换</p>
<p>（3）并发高、业务执行时间长，解决这种类型任务的关键不在于线程池而在于整体架构的设计，看看这些业务里面某些数据是否能做缓存是第一步，增加服务器是第二步，至于线程池的设置，设置参考（2）。最后，业务执行时间长的问题，也可能需要分析一下，看看能不能使用中间件对任务进行拆分和解耦。</p>

          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/spring常用接口之InitializingBean/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/spring常用接口之InitializingBean/" class="post-title-link" itemprop="url">spring常用接口之InitializingBean</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 16:54:55" itemprop="dateCreated datePublished" datetime="2019-06-18T16:54:55+08:00">2019-06-18</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-07-02 19:21:32" itemprop="dateModified" datetime="2019-07-02T19:21:32+08:00">2019-07-02</time>
              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/spring框架/" itemprop="url" rel="index"><span itemprop="name">spring框架</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="spring常用接口简介"><a href="#spring常用接口简介" class="headerlink" title="spring常用接口简介"></a>spring常用接口简介</h2><h3 id="InitializingBean接口"><a href="#InitializingBean接口" class="headerlink" title="InitializingBean接口"></a>InitializingBean接口</h3><ul>
<li><p>作用：实现InitializingBean接口的bean,在初始化bean时都会执行afterPropertiesSet方法<br>afterPropertiesSe</p>
</li>
<li><p>InitializingBean接口源码如下：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">public interface InitializingBean &#123;</span><br><span class="line">    void afterPropertiesSet() throws Exception;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用实例：策略模式+InitializingBean</p>
</li>
<li><p>业务场景：调用登录接口后，需要根据接口返回的不同的错误码，做出不同响应</p>
</li>
<li><p>实现思路：将错误码和场景实现类的映射关系，在bean初始化时通过afterPropertiesSet初试化至Map中（仿照spring初始化beandefinition），调用时通过调用接口返回的错误码get到相应的实现类，InitializingBean在此场景中起到初始化map的作用</p>
</li>
</ul>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 登录场景抽象类</span><br><span class="line"> *</span><br><span class="line"> * @author xiantao.wu</span><br><span class="line"> * @create 2019/5/1711:32</span><br><span class="line"> **/</span><br><span class="line">public abstract class AbstractScene implements InitializingBean &#123;</span><br><span class="line">    private static final Map&lt;Integer, AbstractScene&gt; SCENE_MAP = new ConcurrentHashMap&lt;&gt;();</span><br><span class="line">    //初始化Map</span><br><span class="line">    protected void register(Integer sceneType, AbstractScene scene) &#123;</span><br><span class="line">        SCENE_MAP.put(sceneType, scene);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    public static AbstractScene getScene(Integer sceneType) &#123;</span><br><span class="line">        if (sceneType == null) &#123;</span><br><span class="line">            throw 业务异常</span><br><span class="line">        &#125;</span><br><span class="line">        return SCENE_MAP.get(sceneType);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    //调用统一入口</span><br><span class="line">    public static AppLoginResponse checkLoginResponse(LoginResponse response) &#123;</span><br><span class="line">        Integer sceneType=response.getCode;</span><br><span class="line">        AbstractScene scene = getScene(sceneType);</span><br><span class="line">        if (scene == null) &#123;</span><br><span class="line">           throw 业务异常</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        return scene.check(apiResponse);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    //登录check项抽象方法</span><br><span class="line">    public abstract AppLoginResponse check(ApiResponse&lt;TokenPersonLoginResult&gt; apiResponse);</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>具体实现类：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 场景一:账号存在风险</span><br><span class="line"> *</span><br><span class="line"> * @author xiantao.wu</span><br><span class="line"> * @create 2019/5/1711:35</span><br><span class="line"> **/</span><br><span class="line">@Service</span><br><span class="line">public class RiskAccountScene extends AbstractScene &#123;</span><br><span class="line">    @Autowired</span><br><span class="line">    private PersonService personService;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public void afterPropertiesSet() throws Exception &#123;</span><br><span class="line">        register(Errors.RISK_ACCOUNT.getErrorCode(), this);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public AppLoginResponse check(ApiResponse&lt;TokenPersonLoginResult&gt; apiResponse) &#123;</span><br><span class="line">        //TODO 具体实现逻辑</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">/**</span><br><span class="line"> * 场景二:需要验证手机</span><br><span class="line"> *</span><br><span class="line"> * @author xiantao.wu</span><br><span class="line"> * @create 2019/5/1711:35</span><br><span class="line"> **/</span><br><span class="line">@Service</span><br><span class="line">public class NeedVerifyMobileScene extends AbstractScene &#123;</span><br><span class="line">    @Autowired</span><br><span class="line">    private PersonService personService;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public void afterPropertiesSet() throws Exception &#123;</span><br><span class="line">        register(Errors.NEED_VERIFY_MOBILE.getErrorCode(), this);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    @Override</span><br><span class="line">    public AppLoginResponse check(ApiResponse&lt;TokenPersonLoginResult&gt; apiResponse) &#123;</span><br><span class="line">        //TODO 具体实现逻辑</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">登录调用</span><br><span class="line"></span><br><span class="line"> /**</span><br><span class="line">     * 登录</span><br><span class="line">     */</span><br><span class="line">    @ApiOperation(value = &quot;登录&quot;, tags = &quot;PASSPORT&quot;)</span><br><span class="line">    @PostMapping(value = &quot;/login&quot;)</span><br><span class="line">    public ApiResponse&lt;AppLoginResponse&gt; login(@RequestBody AppLoginRequest appLoginRequest) &#123;</span><br><span class="line">        LoginResponse response = loginService.login(appLoginRequest);</span><br><span class="line">        return ApiResponse.success(AbstractScene.checkLoginResponse(response));</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>


          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/spring常用接口之BeanpostProccesser/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/spring常用接口之BeanpostProccesser/" class="post-title-link" itemprop="url">spring常用接口之BeanpostProccesser</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 16:54:06" itemprop="dateCreated datePublished" datetime="2019-06-18T16:54:06+08:00">2019-06-18</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-07-02 19:21:32" itemprop="dateModified" datetime="2019-07-02T19:21:32+08:00">2019-07-02</time>
              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/spring框架/" itemprop="url" rel="index"><span itemprop="name">spring框架</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="springBean生命周期"><a href="#springBean生命周期" class="headerlink" title="springBean生命周期"></a>springBean生命周期</h2><p>作用：BeanPostProcessor在bean初始化前后做自定义处理</p>
<p>场景：需要自定义swagger,使所有请求显示固定的请求头参数(自定义Docket类)，但是swagger被架构组封装到sdk中，所以在BeanPostProcessor中对Docket的bean做处理</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line"> * 自定义swagger</span><br><span class="line"> *</span><br><span class="line"> * @author xiantao.wu</span><br><span class="line"> * @create 2019/3/269:51</span><br><span class="line"> **/</span><br><span class="line">@Component</span><br><span class="line">public class GiveAppBeanPostProcessor implements BeanPostProcessor &#123;</span><br><span class="line">    //bean初始化之前的操作</span><br><span class="line">    @Override</span><br><span class="line">    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException &#123;</span><br><span class="line">        return bean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    //bean初始化之后的操作</span><br><span class="line">    @Override</span><br><span class="line">    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException &#123;</span><br><span class="line">        //swagger统一增加请求头</span><br><span class="line">        if (&quot;docket&quot;.equals(beanName)) &#123;</span><br><span class="line">            return builderHeader((Docket) bean);</span><br><span class="line">        &#125;</span><br><span class="line">        return bean;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    private Docket builderHeader(Docket docket) &#123;</span><br><span class="line">        List&lt;Parameter&gt; pars = new TreeList();</span><br><span class="line">        pars.add(new ParameterBuilder().name(&quot;x-os-name&quot;).description(&quot;系统类型&quot;).defaultValue(&quot;iOS&quot;)</span><br><span class="line">                .modelRef(new ModelRef(&quot;string&quot;)).parameterType(&quot;header&quot;).required(true).build());</span><br><span class="line"></span><br><span class="line">        pars.add(new ParameterBuilder().name(&quot;x-os-version&quot;).description(&quot;系统版本&quot;).defaultValue(&quot;10.3.3&quot;)</span><br><span class="line">                .modelRef(new ModelRef(&quot;string&quot;)).parameterType(&quot;header&quot;).required(true).build());</span><br><span class="line"></span><br><span class="line">        return docket.globalOperationParameters(pars);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/java多线程之ThreadPoolExcutor/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/java多线程之ThreadPoolExcutor/" class="post-title-link" itemprop="url">java多线程之ThreadPoolExcutor</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 16:53:26" itemprop="dateCreated datePublished" datetime="2019-06-18T16:53:26+08:00">2019-06-18</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-07-02 19:21:32" itemprop="dateModified" datetime="2019-07-02T19:21:32+08:00">2019-07-02</time>
              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/java多线程/" itemprop="url" rel="index"><span itemprop="name">java多线程</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h2 id="一、为什么需要使用线程池"><a href="#一、为什么需要使用线程池" class="headerlink" title="一、为什么需要使用线程池"></a>一、为什么需要使用线程池</h2><ul>
<li><strong>线程创建和销毁的开销非常高</strong>：频繁的创建和销毁线程需要消耗时间，会使响应变慢；同时消耗计算资源。</li>
<li><strong>资源耗尽</strong>：空闲的线程会占用内存，会给垃圾回收带来压力，线程竞争CPU也会产生性能开销，线程池可合理管理空闲线程</li>
<li><strong>稳定性</strong>：在一定范围内，增加线程可以提升系统的处理能力，如果超过这个范围，继续创建线程只会降低执行速度，甚至导致系统OOM,线程池即可以通过程序控制线程数。</li>
</ul>
<h2 id="二、几个常用线程池"><a href="#二、几个常用线程池" class="headerlink" title="二、几个常用线程池"></a>二、几个常用线程池</h2><p>首先看下线程池的构造函数：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line">    public ThreadPoolExecutor(int corePoolSize,</span><br><span class="line">                              int maximumPoolSize,</span><br><span class="line">                              long keepAliveTime,</span><br><span class="line">                              TimeUnit unit,</span><br><span class="line">                              BlockingQueue&lt;Runnable&gt; workQueue,</span><br><span class="line">                              ThreadFactory threadFactory,</span><br><span class="line">                              RejectedExecutionHandler handler) &#123;</span><br><span class="line">        if (corePoolSize &lt; 0 ||</span><br><span class="line">            maximumPoolSize &lt;= 0 ||</span><br><span class="line">            maximumPoolSize &lt; corePoolSize ||</span><br><span class="line">            keepAliveTime &lt; 0)</span><br><span class="line">            throw new IllegalArgumentException();</span><br><span class="line">        if (workQueue == null || threadFactory == null || handler == null)</span><br><span class="line">            throw new NullPointerException();</span><br><span class="line">        this.acc = System.getSecurityManager() == null ?</span><br><span class="line">                null :</span><br><span class="line">                AccessController.getContext();</span><br><span class="line">        this.corePoolSize = corePoolSize;</span><br><span class="line">        this.maximumPoolSize = maximumPoolSize;</span><br><span class="line">        this.workQueue = workQueue;</span><br><span class="line">        this.keepAliveTime = unit.toNanos(keepAliveTime);</span><br><span class="line">        this.threadFactory = threadFactory;</span><br><span class="line">        this.handler = handler;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<ol>
<li><p><strong>newFixedThreadPool</strong>:将创建一个<strong>长度固定的线程池</strong>，每当新提交一个任务时就创建一个新线程，直到达到线程池的最大数量，这时线程池的大小不在变化（如果某个线程发生未预期的Exception而结束，那么线程池会补充一个新线程）。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) &#123;</span><br><span class="line">       return new ThreadPoolExecutor(nThreads, nThreads,</span><br><span class="line">                                     0L, TimeUnit.MILLISECONDS,</span><br><span class="line">                                     new LinkedBlockingQueue&lt;Runnable&gt;(),</span><br><span class="line">                                     threadFactory);</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>newCachedThreadPool</strong>:将创建一个<strong>可缓存的线程池</strong>，如果有线程空闲，会回收空闲线程；如果任务增加时，可添加新线程，线程池的规模不存在任何界限。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">public static ExecutorService newCachedThreadPool() &#123;</span><br><span class="line">       return new ThreadPoolExecutor(0, Integer.MAX_VALUE,</span><br><span class="line">                                     60L, TimeUnit.SECONDS,</span><br><span class="line">                                     new SynchronousQueue&lt;Runnable&gt;());</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>newSingleThreadPool</strong>:将创建一个<strong>单线程的线程池</strong>，如果线程异常结束，将创建另一个线程来替代；阻塞队列为LinkedBlockingQueue，提交的任务可按照顺序执行</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">public static ExecutorService newSingleThreadExecutor() &#123;</span><br><span class="line">        return new FinalizableDelegatedExecutorService</span><br><span class="line">            (new ThreadPoolExecutor(1, 1,</span><br><span class="line">                                    0L, TimeUnit.MILLISECONDS,</span><br><span class="line">                                    new LinkedBlockingQueue&lt;Runnable&gt;()));</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p><strong>newScheduledThreadPool</strong>： 创建了一个<strong>固定长度的线程池,而且以延迟或定时的方式来执行任务</strong>,类似于Timer。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">public ScheduledThreadPoolExecutor(int corePoolSize,</span><br><span class="line">                                   ThreadFactory threadFactory) &#123;</span><br><span class="line">    super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,</span><br><span class="line">          new DelayedWorkQueue(), threadFactory);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

</li>
</ol>
<h2 id="三、线程池的六个重要参数："><a href="#三、线程池的六个重要参数：" class="headerlink" title="三、线程池的六个重要参数："></a>三、线程池的六个重要参数：</h2><ol>
<li><strong>corePoolSize</strong>：核心线程数<ul>
<li>核心线程会一直存活，及时没有任务需要执行</li>
<li>线程数 &lt; corePoolSize时，即使有线程空闲，线程池也会优先创建新线程处理</li>
<li>设置allowCoreThreadTimeout=true（默认false）时，核心线程会超时关闭</li>
</ul>
</li>
<li><strong>queueCapacity</strong>：任务队列容量（阻塞队列）<br> 当核心线程数达到最大时，新任务会放在队列中排队等待执行</li>
<li><strong>maxPoolSize</strong>：最大线程数<ul>
<li>线程数&gt;=corePoolSize，且任务队列已满时。线程池会创建新线程来处理任务</li>
<li>线程数=maxPoolSize，且任务队列已满时，线程池会拒绝处理任务而抛出异常</li>
</ul>
</li>
<li><strong>keepAliveTime</strong>：线程空闲时间<ul>
<li>当线程空闲时间达到keepAliveTime时，线程会退出，直到线程数量=corePoolSize</li>
<li>如果allowCoreThreadTimeout=true，则会直到线程数量=0</li>
</ul>
</li>
<li><strong>allowCoreThreadTimeout</strong>：允许核心线程超时</li>
<li><strong>rejectedExecutionHandler</strong>：任务拒绝处理器,两种情况会拒绝处理任务：<ul>
<li>当线程数已经达到maxPoolSize，切队列已满，会拒绝新任务</li>
<li>当线程池被调用shutdown()后，会等待线程池里的任务执行完毕，再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务，会拒绝新任务</li>
<li>线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy，会抛出异常</li>
</ul>
</li>
<li>拒绝策略：<ul>
<li>AbortPolicy 直接抛出一个RejectedExecutionException，这也是JDK默认的拒绝策略</li>
<li>CallerRunsPolicy 尝试直接运行被拒绝的任务，如果线程池已经被关闭了，任务就被丢弃了</li>
<li>DiscardPolicy 不能执行的任务将被删除</li>
<li>DiscardOldestPolicy 移除最晚的那个没有被处理的任务，然后执行被拒绝的任务。同样，如果线程池已经被关闭了，任务就被丢弃了</li>
<li>自定义：实现RejectedExecutionHandler接口，可自定义处理器</li>
</ul>
</li>
</ol>
<h2 id="四、ThreadPoolExecutor执行顺序："><a href="#四、ThreadPoolExecutor执行顺序：" class="headerlink" title="四、ThreadPoolExecutor执行顺序："></a>四、ThreadPoolExecutor执行顺序：</h2><pre><code>线程池按以下行为执行任务</code></pre><ol>
<li>currentThreadNum &lt; corePoolSize-&gt;创建线程。</li>
<li>corePoolSize =&lt; currentThreadNum ，对列未满，加入队列。</li>
<li>corePoolSize =&lt; currentThreadNum &lt;maxPoolSize ，且任务队列已满,创建线程</li>
<li>corePoolSize =&lt; currentThreadNum &amp;&amp;currentThreadNum&gt;=maxPoolSize ,且任务队列已满,创建线程，抛出异常，拒绝任务</li>
</ol>
<h2 id="五、如何设置参数"><a href="#五、如何设置参数" class="headerlink" title="五、如何设置参数"></a>五、如何设置参数</h2><ul>
<li>默认值<br>corePoolSize=1<br>queueCapacity=Integer.MAX_VALUE<br>maxPoolSize=Integer.MAX_VALUE<br>keepAliveTime=60s<br>allowCoreThreadTimeout=false<br>rejectedExecutionHandler=AbortPolicy()</li>
<li>如何来设置<ol>
<li>需要根据几个值来决定</li>
</ol>
<ul>
<li>tasks ：每秒的任务数，假设为500~1000</li>
<li>taskcost：每个任务花费时间，假设为0.1s</li>
<li>responsetime：系统允许容忍的最大响应时间，假设为1s</li>
</ul>
<ol start="2">
<li>做几个计算</li>
</ol>
<ul>
<li>corePoolSize = 每秒需要多少个线程处理？<br>threadcount = tasks/(1/taskcost) =tasks<em>taskcout =  (500~1000)</em>0.1 = 50~100 个线程。corePoolSize设置应该大于50<br>根据8020原则，如果80%的每秒任务数小于800，那么corePoolSize设置为80即可</li>
<li>queueCapacity = (coreSizePool/taskcost)<em>responsetime<br>计算可得 queueCapacity = 80/0.1</em>1 = 80。意思是队列里的线程可以等待1s，超过了的需要新开线程来执行<br>切记不能设置为Integer.MAX_VALUE，这样队列会很大，线程数只会保持在corePoolSize大小，当任务陡增时，不能新开线程来执行，响应时间会随之陡增。</li>
<li>maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost)<br>计算可得 maxPoolSize = (1000-80)/10 = 92<br>（最大任务数-队列容量）/每个线程每秒处理能力 = 最大线程数</li>
<li>rejectedExecutionHandler：根据具体情况来决定，任务不重要可丢弃，任务重要则要利用一些缓冲机制来处理</li>
<li>keepAliveTime和allowCoreThreadTimeout采用默认通常能满足</li>
</ul>
</li>
</ul>

          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/关于提升工作效率的一点思考/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/关于提升工作效率的一点思考/" class="post-title-link" itemprop="url">关于提升工作效率的一点思考</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 16:52:25" itemprop="dateCreated datePublished" datetime="2019-06-18T16:52:25+08:00">2019-06-18</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-07-02 19:21:32" itemprop="dateModified" datetime="2019-07-02T19:21:32+08:00">2019-07-02</time>
              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/代码之外/" itemprop="url" rel="index"><span itemprop="name">代码之外</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <p>最近参加了一个由TGO鲲鹏会组织线上技术交流活动，主办方邀请了一些大牛做技术分享，其中有个议题就是如何提高工作效率。听完各路大神的分享，然后刚好最近自己负责的项目出了一点问题，平时工作经常也会出现疲于应付的问题，根据高效这个议题，然后结合自己的工作经历，深刻反思了一下，就像总结一点东西，督促自己。</p>
<h4 id="一、能高效的工作，首先要有良好的精神状态"><a href="#一、能高效的工作，首先要有良好的精神状态" class="headerlink" title="一、能高效的工作，首先要有良好的精神状态"></a>一、能高效的工作，首先要有良好的精神状态</h4><p>相信这一点，大家都知道，就不用多说了。最简单也最普遍方式就是保证睡眠（早睡，午睡），锻炼。没有头发的程序员是失败的程序员，，保持良好的作息，健康的生活习惯，才能有良好的精神状态。</p>
<h4 id="二、良好的工作习惯"><a href="#二、良好的工作习惯" class="headerlink" title="二、良好的工作习惯"></a>二、良好的工作习惯</h4><ol>
<li>关于时间</li>
</ol>
<ul>
<li>时间分片，做好计划：每段时间只做一件事，才能保持专注度，专注度才能保证效率，例如：不要同时解决测试提的bug,同时写代码或者写文档，思维中断后再连接是需要时间回顾之前的思路的。</li>
<li>如何分片，如何排序：第一个问题顺序：要事第一，其后可按照优先级排序，第二个问题：分片的粒度，在开启新项目或新需求时，任务都会做拆分，可按照任务的粒度来执行，当然中间不免有一些会议，可以一天预留出一到两个小时作为临时会议或者沟通时间。</li>
<li>避免情绪波动：与产品测试沟通过程中，难免有一些意见不合，比如针对不合理需求，可寻求开发leader或领导介入，尽力去沟通，争取自己的最大化利益，如果最终无法改变，就妥协。比如：加需求，顶头上次都说时间不能顺延，那就只能加班了（如果长期如此，也可以走人了）。</li>
</ul>
<ol start="2">
<li>关于需求</li>
</ol>
<ul>
<li>有备而来，带着疑问沟通：需求评审前，仔细精读需求文档。</li>
<li>明确现状，评估可行性：回顾每一个需求改动点的业务现状及其现有实现逻辑，明确新需求期望与现状的差距，做好开发时间评估和可行性评估，方便在会上提出需求不可行原因以及可能存在的风险。</li>
<li>记录结果，防止纠纷：记下需求中的模糊点，在会上沟通好确定好细节，并以文字的形式记录下疑问点的沟通结果，要求产品经理将疑问点写入公开的需求文档。</li>
<li>正确理解，至关重要：任何时候对需求有疑问，必须找产品沟通确认，正确实现需求才是最重要的，切不可没时间把事情做对，却又时间返工。</li>
</ul>
<ol start="3">
<li>关于会议</li>
</ol>
<ul>
<li>不参加不需要我说话的会：我不需要说话，基本会议与我无关，纯属浪费时间。</li>
<li>参加了就要高效： 凡是会议必有主题；凡是主题必有议程；凡是议程必有决议；凡是决议必有跟踪；凡是跟踪必有结果；凡是结果必有责任；凡是责任必有奖惩；凡是奖惩必须透明。最后一次会议达成共识，比面反复耗费时间。</li>
</ul>
<ol start="4">
<li>关于反馈</li>
</ol>
<ul>
<li>定时反馈进度：阶段性向leader或者PMO反馈开发进度，树立良好的做事风格，同时也可减少因为询问而被打断思路。</li>
<li>主动反馈，不要做反馈黑洞：遇到技术难点，及时与leader讨论解决方案；</li>
</ul>
<ol start="5">
<li>关于工作中被打断</li>
</ol>
<ul>
<li>来自项目经理的打断：同时是询问开发进度，定期反馈，主动反馈。</li>
<li>来自来自产品的打断：在审批阶段解决掉疑问，正式开发后只专注开发。</li>
<li>来自测试的打断：文档写详细，避免被询问打断，将他人带到自己的工作习惯中，避免被牵着走。</li>
</ul>
<ol start="6">
<li>关于面子</li>
</ol>
<ul>
<li>需求沟通过程中，有疑问就要问，切记因为不好意思，而不沟通，需求的正确执行是第一要务，不懂就要问，爱面子只会阻碍你的进步。</li>
</ul>
<ol start="7">
<li>关于工具</li>
</ol>
<ul>
<li>熟练掌握常用工具：快捷键，代码不全功能（如idea的live template可定制代码生成），减少鼠标键盘切换，保持连贯的思维</li>
<li>重复工作脚本化：autohotkey,windows批处理文件</li>
<li>熟悉常用工具包：比如：Apache common,google guawa。</li>
</ul>
<h4 id="三、具体小习惯总结"><a href="#三、具体小习惯总结" class="headerlink" title="三、具体小习惯总结"></a>三、具体小习惯总结</h4><ol>
<li>每日总结，下班总结工作内容，整理次日需完成的内容。</li>
<li>早到半小时，安排工作计划，对一天进行规划</li>
<li>在提测前，花一天时间整体review代码，对比master与develop,整体评估风险点，并优化代码。</li>
</ol>

          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
      

  

  
  
  

  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="http://www.wuxiantao123.cn/2019/06/18/java8之Stream-Api/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="Thomas Wu">
      <meta itemprop="description" content="人帅也要多读书，多学习，多运动">
      <meta itemprop="image" content="/images/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="费曼的门徒">
    </span>

    
      <header class="post-header">

        
        
          <h2 class="post-title" itemprop="name headline">
                
                
                <a href="/2019/06/18/java8之Stream-Api/" class="post-title-link" itemprop="url">java 8之Stream Api解析</a>
              
            
          </h2>
        

        <div class="post-meta">
          <span class="post-time">

            
            
            

            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">发表于</span>
              

              
                
              

              <time title="创建时间：2019-06-18 16:50:30" itemprop="dateCreated datePublished" datetime="2019-06-18T16:50:30+08:00">2019-06-18</time>
            

            
              

              
                
                <span class="post-meta-divider">|</span>
                

                <span class="post-meta-item-icon">
                  <i class="fa fa-calendar-check-o"></i>
                </span>
                
                  <span class="post-meta-item-text">更新于</span>
                
                <time title="修改时间：2019-08-22 22:41:28" itemprop="dateModified" datetime="2019-08-22T22:41:28+08:00">2019-08-22</time>
              
            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">分类于</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing"><a href="/categories/java基础/" itemprop="url" rel="index"><span itemprop="name">java基础</span></a></span>

                
                
              
            </span>
          

          
            
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        
          
            <h3 id="一、流操作之中间操作简介"><a href="#一、流操作之中间操作简介" class="headerlink" title="一、流操作之中间操作简介"></a>一、流操作之中间操作简介</h3><p>中间操作主要是用来对Stream做出相应转换及限制流，实际上是将源Stream转换为一个新的Stream，以达到需求效果。</p>
<h3 id="二、常用中间操作方法"><a href="#二、常用中间操作方法" class="headerlink" title="二、常用中间操作方法"></a>二、常用中间操作方法</h3><table>
<thead>
<tr>
<th>操作</th>
<th>类型</th>
<th>返回类型</th>
<th>操作参数</th>
<th>函数描述符</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>filter</td>
<td>中间</td>
<td>Stream<t></t></td>
<td>Predicate<t></t></td>
<td>T -&gt; boolean</td>
<td>返回参数函数为true的元素的流</td>
</tr>
<tr>
<td>map</td>
<td>中间</td>
<td>Stream<t></t></td>
<td>Function&lt;T, R&gt;</td>
<td>T -&gt; R</td>
<td>参数函数会被应用到每个元素上，并将其映射成一个新的元素</td>
</tr>
<tr>
<td>flatMap</td>
<td>中间</td>
<td>Stream<t></t></td>
<td>Function&lt;T, R&gt;</td>
<td>T -&gt; R</td>
<td>flatmap 方法让你把一个流中的每个值都换成另一个流，然后把所有的流连接起来成为一个流。</td>
</tr>
<tr>
<td>limit</td>
<td>中间</td>
<td>Stream<t></t></td>
<td></td>
<td></td>
<td>返回前n个元素的流</td>
</tr>
<tr>
<td>skip</td>
<td>中间</td>
<td>Stream<t></t></td>
<td></td>
<td></td>
<td>返回一个跳过前n个元素的流（不足n个元素，返回一个空流）</td>
</tr>
<tr>
<td>sorted</td>
<td>中间</td>
<td>Stream<t></t></td>
<td>Comparator<t></t></td>
<td>(T, T) -&gt; int</td>
<td>按照传入的Comparator安排续</td>
</tr>
<tr>
<td>distinct</td>
<td>中间</td>
<td>Stream<t></t></td>
<td></td>
<td></td>
<td>根据流所生成元素的hashCode 和 equals 方法，实现去重后的流</td>
</tr>
</tbody></table>
<h3 id="filter方法"><a href="#filter方法" class="headerlink" title="filter方法"></a>filter方法</h3><p>使用实例：遍历出相同的字符串</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Stream.of(<span class="string">"a"</span>, <span class="string">"a"</span>, <span class="string">"b"</span>)</span><br><span class="line">               .filter((s) -&gt; s.startsWith(<span class="string">"a"</span>))</span><br><span class="line">               .forEach(System.out::println);</span><br><span class="line"> <span class="comment">//return:"a","a"</span></span><br></pre></td></tr></table></figure>

<h3 id="map方法"><a href="#map方法" class="headerlink" title="map方法"></a>map方法</h3><p>类似的有：mapToDouble，mapToInt，mapToLong。<br>使用实例：求和处理</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Stream.of(<span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>)</span><br><span class="line">               .mapToInt(Integer::intValue)</span><br><span class="line">               .sum();</span><br><span class="line">       <span class="comment">//return:3</span></span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Long l=Stream.of(<span class="number">1L</span>,<span class="number">2L</span>,<span class="number">4L</span>)</span><br><span class="line">                .mapToLong(Long::longValue)</span><br><span class="line">                .sum();</span><br><span class="line"><span class="comment">//return:7</span></span><br></pre></td></tr></table></figure>

<h3 id="flatMap方法"><a href="#flatMap方法" class="headerlink" title="flatMap方法"></a>flatMap方法</h3><p>使用实例： 给 定 单 词 列 表”Hello”,”World” ，你想要返回列表 “H”,”e”,”l”, “o”,”W”,”r”,”d” ，做法就是先分割，在去重，返回字符串数组。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">List&lt;String&gt; uniqueCharacters =</span><br><span class="line">              Stream.of(<span class="string">"heelo"</span>,<span class="string">"adafa"</span>)</span><br><span class="line">                      .map(w -&gt; w.split(<span class="string">""</span>))</span><br><span class="line">                      .flatMap(Arrays::stream)</span><br><span class="line">                      .distinct()</span><br><span class="line">                      .collect(Collectors.toList());</span><br></pre></td></tr></table></figure>

<h3 id="limit方法和skip方法"><a href="#limit方法和skip方法" class="headerlink" title="limit方法和skip方法"></a>limit方法和skip方法</h3><p>使用实例：取前n个元素</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> Stream.of(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>)</span><br><span class="line">	   .limit(<span class="number">3</span>)</span><br><span class="line">	    .forEach(i -&gt; System.out.println(i));</span><br><span class="line"><span class="comment">//return 1,2,3</span></span><br></pre></td></tr></table></figure>

<p>使用实例：跳过前3个元素</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"> Stream.of(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>)</span><br><span class="line">	   .skip(<span class="number">3</span>)</span><br><span class="line">	    .forEach(System.out::println);</span><br><span class="line"><span class="comment">//return 4,5</span></span><br></pre></td></tr></table></figure>

<h3 id="distinct方法"><a href="#distinct方法" class="headerlink" title="distinct方法"></a>distinct方法</h3><p>使用实例：去重操作</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Stream.of(<span class="string">"a"</span>, <span class="string">"b"</span>, <span class="string">"c"</span>, <span class="string">"c"</span>)</span><br><span class="line">                .distinct()</span><br><span class="line">                .forEach(System.out::println);</span><br><span class="line"> <span class="comment">//return:a,b,c</span></span><br></pre></td></tr></table></figure>

<p>参考博客：<a href="https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/" target="_blank" rel="noopener">java8 stream-api</a></p>

          
        
      
    </div>

    

    
    
    

    

    
      
    
    

    

    <footer class="post-footer">
      

      

      

      
      
        <div class="post-eof"></div>
      
    </footer>
  </div>
  
  
  
  </article>


    
  </section>

  
  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/"><i class="fa fa-angle-left" aria-label="上一页"></i></a><a class="page-number" href="/">1</a><span class="page-number current">2</span><a class="page-number" href="/page/3/">3</a><a class="extend next" rel="next" href="/page/3/"><i class="fa fa-angle-right" aria-label="下一页"></i></a>
  </nav>



          </div>
          

        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    <div class="sidebar-inner">

      

      

      <div class="site-overview-wrap sidebar-panel sidebar-panel-active">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/images/avatar.jpg" alt="Thomas Wu">
            
              <p class="site-author-name" itemprop="name">Thomas Wu</p>
              <div class="site-description motion-element" itemprop="description">人帅也要多读书，多学习，多运动</div>
          </div>

          
            <nav class="site-state motion-element">
              
                <div class="site-state-item site-state-posts">
                
                  <a href="/archives/">
                
                    <span class="site-state-item-count">24</span>
                    <span class="site-state-item-name">日志</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-categories">
                  
                    
                      <a href="/categories/">
                    
                  
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">9</span>
                    <span class="site-state-item-name">分类</span>
                  </a>
                </div>
              

              
                
                
                <div class="site-state-item site-state-tags">
                  
                    
                      <a href="/tags/">
                    
                  
                    
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                      
                    
                    <span class="site-state-item-count">6</span>
                    <span class="site-state-item-name">标签</span>
                  </a>
                </div>
              
            </nav>
          

          

          

          
            <div class="links-of-author motion-element">
              
                <span class="links-of-author-item">
                  
                  
                    
                  
                  
                    
                  
                  <a href="https://github.com/peach-boy" title="GitHub &rarr; https://github.com/peach-boy" rel="noopener" target="_blank"><i class="fa fa-fw fa-github"></i>GitHub</a>
                </span>
              
                <span class="links-of-author-item">
                  
                  
                    
                  
                  
                    
                  
                  <a href="/1414924381@qq.com" title="E-Mail &rarr; 1414924381@qq.com"><i class="fa fa-fw fa-envelope"></i>E-Mail</a>
                </span>
              
            </div>
          

          

          
          
            <div class="links-of-blogroll motion-element links-of-blogroll-block">
              <div class="links-of-blogroll-title">
                <i class="fa  fa-fw fa-link"></i>
                友情链接
              </div>
              <ul class="links-of-blogroll-list">
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.cnblogs.com/xrq730/" title="https://www.cnblogs.com/xrq730/" rel="noopener" target="_blank">五月的仓颉</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.w3cschool.cn/architectroad/" title="https://www.w3cschool.cn/architectroad/" rel="noopener" target="_blank">沈剑架构师之路</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://crossoverjie.top/" title="https://crossoverjie.top/" rel="noopener" target="_blank">crossoverjie</a>
                  </li>
                
                  <li class="links-of-blogroll-item">
                    <a href="https://www.jianshu.com/u/2766e4cfc391" title="https://www.jianshu.com/u/2766e4cfc391" rel="noopener" target="_blank">高广超</a>
                  </li>
                
              </ul>
            </div>
          

          
            
          
          

        </div>
      </div>

      

      

    </div>
  </aside>
  


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2019</span>
  <span class="with-love" id="animate">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Thomas Wu</span>

  

  
</div>









        








        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

    

    
  </div>

  

<script>
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>


























  
  <script src="/lib/jquery/index.js?v=3.4.1"></script>

  
  <script src="/lib/velocity/velocity.min.js?v=1.2.1"></script>

  
  <script src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>


  


  <script src="/js/utils.js?v=7.1.2"></script>

  <script src="/js/motion.js?v=7.1.2"></script>



  
  


  <script src="/js/affix.js?v=7.1.2"></script>

  <script src="/js/schemes/pisces.js?v=7.1.2"></script>




  

  


  <script src="/js/next-boot.js?v=7.1.2"></script>


  

  

  

  



  




  

  

  

  

  

  

  

  

  

  

  

  

  

  

</body>
</html>
